using System;

namespace scripts.net
{
    public class ByteArray
    {
        //缓冲区
        public byte[] bytes;

        //读写位置
        public int readIdx = 0;
        public int writeIdx = 0;

        //默认大小
        const int DEFAULT_SIZE = 1024;

        //初始大小
        private int intiSize;

        //容量
        private int capacity;

        //剩余空间
        public int remain
        {
            get { return capacity - writeIdx; }
        }

        //数据长度
        public int length
        {
            get { return writeIdx - readIdx; }
        }

        public ByteArray(byte[] defaultBytes)
        {
            bytes = defaultBytes;
            writeIdx = defaultBytes.Length;
            capacity = defaultBytes.Length;
            intiSize = defaultBytes.Length;
        }

        public ByteArray(int size = DEFAULT_SIZE)
        {
            bytes = new byte[size];
            capacity = size;
            intiSize = size;
        }

        //重设尺寸
        public void Resize(int size)
        {
            if (size < length) return;
            if (size < intiSize) return;
            int n = 1;
            while (n < size) n *= 2;
            capacity = n;
            byte[] newBytes = new byte[capacity];
            Array.Copy(bytes, readIdx, newBytes, 0, length);
            bytes = newBytes;
            writeIdx = length;
            readIdx = 0;
        }


        //写入
        public int Write(byte[] bs, int idx, int cnt)
        {
            if (remain < cnt)
            {
                //重设尺寸需加上原有数据长度
                Resize(length + cnt);
            }

            Array.Copy(bs, idx, bytes, writeIdx, cnt);
            writeIdx += cnt;
            return cnt;
        }

        //读入
        public int Read(byte[] bs, int idx, int cnt)
        {
            cnt = Math.Min(cnt, length); //最多只能读length个长度，因此取Min
            Array.Copy(bytes, readIdx, bs, idx, cnt);
            readIdx += cnt;
            MoveLowLength();
            return cnt;
        }

        //用于读缓存区：较短数据移动
        //TODO 是否有必要呢
        public void MoveLowLength()
        {
            if (length > 8) return;
            if (length > 0)
            {
                Array.Copy(bytes, readIdx, bytes, 0, length);
            }

            //当length为0，即数据全部被读取时，直接移动readIdx即可
            writeIdx = length;
            readIdx = 0;
        }

        public Int16 ReadInt16()
        {
            if (length < 2) return 0;
            Int16 ret = (Int16) ((bytes[readIdx + 1] << 8) | bytes[readIdx]);
            readIdx += 2;
            MoveLowLength();
            return ret;
        }

        public Int32 ReadInt32()
        {
            if (length < 4) return 0;
            Int32 ret = (Int32) ((bytes[readIdx + 3] << 24) | 
                                 (bytes[readIdx + 2] << 16) | 
                                 (bytes[readIdx + 1] << 8) |
                                 bytes[readIdx]);
            readIdx += 4;
            MoveLowLength();
            return ret;
        }
        
    }
}